home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-16  |  21.9 KB  |  843 lines

  1. /* 
  2.  * main.c --
  3.  *    
  4.  *    This file contains the initialization and file-system interface
  5.  *    routines for the Sprite Internet Protocol Server.
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/main.c,v 1.23 92/06/16 13:02:30 jhh Exp $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include "sprite.h"
  24. #include "inet.h"
  25. #include "ipServer.h"
  26. #include "stat.h"
  27. #include "socket.h"
  28. #include "route.h"
  29. #include "raw.h"
  30. #include "ip.h"
  31. #include "icmp.h"
  32. #include "tcp.h"
  33. #include "udp.h"
  34.  
  35. #include "netInet.h"
  36. #include "dev/pdev.h"
  37. #include "spriteTime.h"
  38. #include "proc.h"
  39.  
  40. #include "option.h"
  41. #include <stdio.h>
  42. #include "fs.h"
  43. #include "sys/file.h"
  44.  
  45. /*
  46.  * Command line options.
  47.  */
  48.  
  49. Boolean ips_Debug = FALSE;
  50. static Boolean detach = TRUE;
  51. static char defaultConfigFile[100] = "/etc/ipServer.config";
  52. static char *configFile = defaultConfigFile;
  53. static char *ipAddress = (char *) NULL;
  54.  
  55. static Option optionArray[] = {
  56.     {OPT_TRUE,   "d", (Address)&ips_Debug, "Turn on debugging output"},
  57.     {OPT_STRING, "c", (Address)&configFile, "Name of configuration file"},
  58.     {OPT_STRING, "i", (Address)&ipAddress, "IP address"},
  59.     {OPT_FALSE,  "b", (Address)&detach, "Don't run in background"},
  60. };
  61. static int numOptions = sizeof(optionArray) / sizeof(Option);
  62.  
  63. char        myHostName[100];
  64.  
  65. typedef struct Sock_PrivInfo *PrivPtr;
  66.  
  67. static void     PdevRequestHandler();
  68. static void     PdevControlHandler();
  69. static int     PrintMemStats();
  70. static int     ToggleDebug();
  71. static int     PrintInfoAndDebug();
  72. #ifdef TEST_DISCONNECT
  73. static int ToggleDisconnect();
  74. int    ips_Disconnect = 0;
  75. #endif
  76.  
  77. /*
  78.  *----------------------------------------------------------------------
  79.  *
  80.  * main --
  81.  *
  82.  *      The main program for the Internet Protocol Server. The
  83.  *      initialization routines of the important modules are called to
  84.  *      set up their data structures. The socket pseudo-devices and the
  85.  *      network device are opened and the FS dispatcher is called to
  86.  *      process events from them.
  87.  *
  88.  * Results:
  89.  *    None.
  90.  *
  91.  * Side effects:
  92.  *    Files are opened. Signal handlers are established.
  93.  *
  94.  *----------------------------------------------------------------------
  95.  */
  96.  
  97. void
  98. main(argc, argv)
  99.     int        argc;
  100.     char    **argv;
  101. {
  102.     int            streamID;
  103.     Sig_Action        sigAction;
  104.     Proc_PID        pid;
  105.     char        deviceName[100];
  106. #ifdef DEBUG
  107.     extern int        Sys_PrintNumCalls();
  108. #endif DEBUG
  109.     extern int        memAllowFreeingFree;
  110.  
  111.     /*
  112.      * Turn on checks for duplicate frees in the memory allocator.
  113.      */
  114.  
  115.     memAllowFreeingFree = 0;
  116.  
  117.     IP_MemBin();
  118.     TCP_MemBin();
  119.     Mem_Bin(sizeof(Sock_BufDataInfo));
  120.     Mem_Bin(sizeof(Sock_SharedInfo));
  121.     Mem_Bin(sizeof(Sock_PrivInfo));
  122.     Mem_SetPrintProc(fprintf, (ClientData)stderr);
  123.  
  124.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  125.  
  126.     /*
  127.      * Print debugging information when the signals are caught. 
  128.      */
  129.  
  130. #define SetHandler(sig, routine) \
  131.     sigAction.action = SIG_HANDLE_ACTION; \
  132.     sigAction.handler = routine; \
  133.     sigAction.sigHoldMask = 1 << (sig-1); \
  134.     if (Sig_SetAction(sig, &sigAction, NULL) != SUCCESS) { \
  135.     (void) fprintf(stderr, "main: can't set signal handler %d\n", sig); \
  136.     }
  137.  
  138.     SetHandler(25, ToggleDebug);
  139.     SetHandler(26, Stat_PrintInfo);
  140.     SetHandler(27, Sock_PrintInfo);
  141. #ifdef TEST_DISCONNECT
  142.     SetHandler(28, ToggleDisconnect);
  143. #else
  144.     SetHandler(28, PrintMemStats);
  145. #endif
  146. #ifdef DEBUG
  147.     SetHandler(29, Sys_PrintNumCalls);
  148. #endif DEBUG
  149.     SetHandler(30, PrintInfoAndDebug);
  150.  
  151.  
  152.     setlinebuf(stderr);
  153. #ifndef sun4
  154.     {
  155.     char    *Version();
  156.     (void) fprintf(stderr, "Sprite Internet Protocol Server: %s\n", 
  157.             Version());
  158.     }
  159. #endif sun4
  160.  
  161.     if (gethostname(myHostName, sizeof(myHostName)) != 0) {
  162.     panic("Can't find my hostname\n");
  163.     }
  164.  
  165.     Rte_AddressInit(myHostName, configFile, ipAddress);
  166.  
  167.     Sock_Init();
  168.  
  169.     Sys_GetTimeOfDay(&stats.startTime, (int *) NULL, (Boolean *) NULL);
  170.  
  171.     IP_Init();
  172.     ICMP_Init();
  173.     UDP_Init();
  174.     TCP_Init(stats.startTime.seconds);
  175.  
  176.  
  177.     /*
  178.      * Open the pseudo-devices that correspond to the stream (TCP), 
  179.      * datagram (UDP) and raw (IP) socket abstractions. The raw socket
  180.      * is opened with 0600 permission so only set-root-uid programs can 
  181.      * access it.
  182.      */
  183.  
  184.     (void) umask(0);
  185.  
  186.     (void) sprintf(deviceName, INET_STREAM_NAME_FORMAT, myHostName);
  187.     streamID = open(deviceName, O_RDONLY|O_CREAT|O_MASTER, 0666);
  188.     if (streamID < 0) {
  189.     perror(deviceName);
  190.     exit(1);
  191.     }
  192.     Fs_EventHandlerCreate(streamID, FS_READABLE, PdevControlHandler, 
  193.             (ClientData) TCP_PROTO_INDEX);
  194.  
  195.  
  196.     (void) sprintf(deviceName, INET_DGRAM_NAME_FORMAT, myHostName);
  197.     streamID = open(deviceName, O_RDONLY|O_CREAT|O_MASTER, 0666);
  198.     if (streamID < 0) {
  199.     perror(deviceName);
  200.     exit(1);
  201.     }
  202.     Fs_EventHandlerCreate(streamID, FS_READABLE, PdevControlHandler,
  203.             (ClientData) UDP_PROTO_INDEX);
  204.  
  205.  
  206.     (void) sprintf(deviceName, INET_RAW_NAME_FORMAT, myHostName);
  207.     streamID = open(deviceName, O_RDONLY|O_CREAT|O_MASTER, 0600);
  208.     if (streamID < 0) {
  209.     perror(deviceName);
  210.     exit(1);
  211.     }
  212.     Fs_EventHandlerCreate(streamID, FS_READABLE, PdevControlHandler, 
  213.             (ClientData) RAW_PROTO_INDEX);
  214.  
  215.  
  216.     pid = getpid(); 
  217.     (void) fprintf(stderr, "PID = %x\n", pid);
  218.  
  219.  
  220.     /*
  221.      * Now that everything is set up, run in the background if the
  222.      * debug flag is not set.
  223.      */
  224.     if (!ips_Debug && detach) {
  225.     Proc_Detach(0);
  226.     }
  227.  
  228.  
  229.     /*
  230.      * Everything's initialized. Start processing events from the
  231.      * the socket pseudo-devices and the network device.
  232.      */
  233.     while (TRUE) {
  234.     stats.misc.dispatchLoop++;
  235.     Fs_Dispatch();
  236.     IP_DelayedOutput();
  237.     }
  238. }
  239.  
  240.  
  241. /*
  242.  *----------------------------------------------------------------------
  243.  *
  244.  * PdevControlHandler --
  245.  *
  246.  *    This routine handles the creation of new pseudo-device connections 
  247.  *    to the server from client programs. It is called from the
  248.  *    FS dispatcher whenever one of "stream/datagram/raw" control streams
  249.  *    become readable. A socket is created for the connection. Further
  250.  *    requests on the new stream will be handled by PdevRequestHandler()
  251.  *    (or UdpRequestHandler)
  252.  *
  253.  * Results:
  254.  *    None.
  255.  *
  256.  * Side effects:
  257.  *    A new socket is created for the connection.
  258.  *
  259.  *----------------------------------------------------------------------
  260.  */
  261.  
  262. static void
  263. PdevControlHandler(clientData, streamID, eventMask)
  264.     ClientData    clientData;    /* Protocol index # for the socket type. */
  265.     int        streamID;    /* ID of stream that became readable, writable,
  266.                  * or has an exception condition ready. */
  267.     int        eventMask;    /* Mask to show what event happened. A combo of
  268.                  * Should be just FS_READABLE. */
  269. {
  270.     ReturnStatus    status;
  271.     Pdev_Notify        notify;
  272.     Pdev_SetBufArgs    bufArgs;
  273.     SockPdevState    *sockPdevPtr;
  274.     int            amount;
  275.     int            state;
  276.     int            reqBufSize;
  277.     int            bigWrites;
  278.     int            writeBehind;
  279.     void        (*handler)();
  280.  
  281.     if (!(eventMask & FS_READABLE)) {
  282.     panic("PdevControlHandler: bad event mask %x\n", eventMask);
  283.     }
  284.  
  285.     /*
  286.      * Read the notify message from the control stream.
  287.      */
  288.  
  289.     amount = read(streamID, (Address)¬ify, sizeof(notify));
  290.     if (amount < 0) {
  291.     perror("PdevControlHandler: read notify");
  292.     exit(1);
  293.     } else if (amount != sizeof(notify)) {
  294.     panic("PdevControlHandler: short read (%d) of the notify\n", amount);
  295.     exit(1);
  296.     } else if (notify.magic != PDEV_NOTIFY_MAGIC) {
  297.     panic("PdevControlHandler: bad magic # (%x) in the notify\n", 
  298.         notify.magic);
  299.     exit(1);
  300.     }
  301.  
  302.     sockPdevPtr = (SockPdevState *)malloc(sizeof(SockPdevState));
  303.     switch ((int)clientData) {
  304.     case TCP_PROTO_INDEX:
  305.         sockPdevPtr->reqBufSize = TCP_REQUEST_BUF_SIZE;
  306.         sockPdevPtr->protoIndex = TCP_PROTO_INDEX;
  307.         bigWrites = TRUE;
  308.         writeBehind = FALSE;
  309.         break;
  310.     case UDP_PROTO_INDEX:
  311.         sockPdevPtr->reqBufSize = UDP_REQUEST_BUF_SIZE;
  312.         sockPdevPtr->protoIndex = UDP_PROTO_INDEX;
  313.         bigWrites = FALSE;
  314.         writeBehind = UDP_WRITE_BEHIND;
  315.         break;
  316.     case RAW_PROTO_INDEX:
  317.         sockPdevPtr->reqBufSize = RAW_REQUEST_BUF_SIZE;
  318.         sockPdevPtr->protoIndex = RAW_PROTO_INDEX;
  319.         bigWrites = FALSE;
  320.         writeBehind = FALSE;
  321.         break;
  322.     }
  323.     /*
  324.      * Allocate the pseudo-device request buffer, leaving room at the
  325.      * front to create packet headers, and adding enough room to account
  326.      * for the pdev message header in front of the data.
  327.      * Make sure the request buffer is a multiple of the word size.
  328.      * (The kernel should do this.)
  329.      */
  330.     sockPdevPtr->reqBufSize += sizeof(Pdev_Request) + sizeof(int);
  331.     sockPdevPtr->reqBufSize &= ~(sizeof(int) - 1);
  332.     sockPdevPtr->requestBuf = (Address) malloc(sockPdevPtr->reqBufSize +
  333.                         IPS_ROOM_FOR_HEADERS);
  334.     bufArgs.requestBufAddr = sockPdevPtr->requestBuf + IPS_ROOM_FOR_HEADERS;
  335.     bufArgs.requestBufSize = sockPdevPtr->reqBufSize;
  336.     bufArgs.readBufAddr = (Address) NULL;
  337.     bufArgs.readBufSize = 0;
  338.     status = Fs_IOControl(notify.newStreamID, IOC_PDEV_SET_BUF,
  339.         sizeof(bufArgs), (Address) &bufArgs, 
  340.         0, (Address) NULL);
  341.     if (status != SUCCESS){
  342.     Stat_PrintMsg(status, "PdevControlHandler: ioc set buf");
  343.     exit(1);
  344.     }
  345.     status = Fs_IOControl(notify.newStreamID, IOC_PDEV_BIG_WRITES,
  346.         sizeof(state), (Address) &bigWrites, 
  347.         0, (Address) NULL);
  348.     if (status != SUCCESS){
  349.     Stat_PrintMsg(status, "PdevControlHandler: ioc big write");
  350.     exit(1);
  351.     }
  352.     status = Fs_IOControl(notify.newStreamID, IOC_PDEV_WRITE_BEHIND,
  353.         sizeof(state), (Address) &writeBehind, 
  354.         0, (Address) NULL);
  355.     if (status != SUCCESS){
  356.     Stat_PrintMsg(status, "PdevControlHandler: ioc write behind");
  357.     exit(1);
  358.     }
  359.  
  360.     Fs_EventHandlerCreate(notify.newStreamID, FS_READABLE, PdevRequestHandler,
  361.                 (ClientData)sockPdevPtr);
  362. }
  363.  
  364.  
  365. static int origFirstByte;
  366.  
  367. /*
  368.  *----------------------------------------------------------------------
  369.  *
  370.  * PdevRequestHandler --
  371.  *
  372.  *    Handle an request from a client accessing a socket pseudo-device.
  373.  *    We read a short message off the request stream that indicates
  374.  *    where in the buffer the next request message(s) are.  Depending
  375.  *    on the client's operation, we may allocate a return data block
  376.  *    that gets filled in by the socket routine.  We reply with a
  377.  *    return status for the client's system call and, optionally, the
  378.  *    return data block.
  379.  *
  380.  * Results:
  381.  *    None.
  382.  *
  383.  * Side effects:
  384.  *    The operation-specific routines may cause side-effects.
  385.  *
  386.  *----------------------------------------------------------------------
  387.  */
  388.  
  389. static void
  390. PdevRequestHandler(clientData, streamID, eventMask)
  391.     ClientData    clientData;    /* Token passed the Sock_ routines to identify
  392.                  * a socket. */
  393.     int        streamID;    /* ID of stream that became readable, writable
  394.                  * or has an exception condition ready. */
  395.     int        eventMask;    /* Mask to show what event happened.
  396.                  * Must be FS_READABLE. */
  397. {
  398.     ReturnStatus    status;
  399.     register Pdev_Request    *requestPtr;
  400.     Pdev_Reply    reply;
  401.     Pdev_BufPtrs    bufPtrs;
  402.     int            amount;
  403.     Address        requestData;
  404.     int            messageSize;
  405.     int            replySize;
  406.     Pdev_Op        operation;
  407.     /*
  408.      * All requests, except PDEV_OPEN, get passed the socket private pointer
  409.      * as the client data from Fs_Dispatch.
  410.      */
  411.     Sock_PrivInfo    *privPtr = (Sock_PrivInfo *)clientData;
  412.  
  413.  
  414.     if (!(eventMask & FS_READABLE)) {
  415.     panic("PdevRequestHandler: bad event mask %x\n", 
  416.                 eventMask);
  417.     }
  418.  
  419.     /*
  420.      * Read the short request header that tells us where in the buffer
  421.      * the next request message is.  Check size and magic number.
  422.      */
  423.  
  424.     amount = read(streamID, (Address)&bufPtrs, sizeof(bufPtrs));
  425.     if (amount  != sizeof(bufPtrs)) {
  426.     perror("PdevRequestHandler: get ptr ioctl");
  427.     exit(1);
  428.     } else if (bufPtrs.magic != PDEV_BUF_PTR_MAGIC) {
  429.     panic("PdevControlHandler: bad magic # (%x) in the bufPtrs\n", 
  430.         bufPtrs.magic);
  431.     exit(1);
  432.     } 
  433.  
  434.     origFirstByte = bufPtrs.requestFirstByte;
  435.     while (bufPtrs.requestFirstByte < bufPtrs.requestLastByte) {
  436.     requestPtr = (Pdev_Request *)
  437.             &bufPtrs.requestAddr[bufPtrs.requestFirstByte];
  438.     if (requestPtr->hdr.magic != PDEV_REQUEST_MAGIC) {
  439.         printf("PdevControlHandler: bad magic # (%x) comitting hari-kari\n",
  440.             requestPtr->hdr.magic);
  441. #ifdef notdef
  442.         /*
  443.          * This will put us more cleanly into the debugger than a panic
  444.          * will.
  445.          */
  446.         *(int *)0 = 100;
  447.         exit(1);
  448. #endif
  449.         /*
  450.          * Hack to attempt to get around the server lieing to us by
  451.          * telling us that there is more data than there really is.
  452.          */
  453.         bufPtrs.requestFirstByte = bufPtrs.requestLastByte + 1;
  454.         break;
  455.     } 
  456.     requestData = (Address)((Address)requestPtr + sizeof(Pdev_Request));
  457.     reply.replySize = 0;
  458.     reply.replyBuf = (Address) NULL;
  459.  
  460.     /*
  461.      * Decode the operation and call a routine for the operation.
  462.      * The operation handler may overwrite the request header with
  463.      * a packet header, so we are careful not to use anything from
  464.      * the request header after calling the service procedure.
  465.      */
  466.     messageSize = requestPtr->hdr.messageSize;
  467.     replySize = requestPtr->hdr.replySize;
  468.     operation = requestPtr->hdr.operation;
  469.     switch (operation) {
  470.  
  471.  
  472.         case PDEV_OPEN: {
  473.             /*
  474.              * Create a new socket structure. If the open was 
  475.              * successful, create an event handler to handle future 
  476.              * requests on the stream.  Sock_Open returns a token 
  477.              * for the new socket, which is associated with the event 
  478.              * handler for the socket's stream.
  479.              *
  480.              * The first arg. to Sock_Open ("clientData") is a pointer
  481.              * to some state about the pseudo-device setup.
  482.              */
  483.  
  484.             reply.status = Sock_Open((SockPdevState *) clientData, 
  485.                     requestPtr->hdr.operation == PDEV_OPEN,
  486.                     streamID,
  487.                     requestPtr->param.open.flags, 
  488.                     requestPtr->param.open.pid, 
  489.                     requestPtr->param.open.hostID, 
  490.                     requestPtr->param.open.uid, 
  491.                     -1, /* no more client ID */
  492.                     &privPtr);
  493.             free((char *)clientData);
  494.             if (reply.status == SUCCESS) {
  495.             /*
  496.              * Save the address of the socket data structure
  497.              * with the stream so subsequent requests can
  498.              * access it.
  499.              */
  500.             (void)Fs_EventHandlerChangeData(streamID,
  501.                             (ClientData)privPtr);
  502.             reply.selectBits = Sock_Select(privPtr, TRUE); 
  503.             } else {
  504.             reply.selectBits = 0;
  505.             }
  506.             PdevReply(streamID, &reply, "open");
  507.         }
  508.         break;
  509.  
  510.  
  511.         case PDEV_CLOSE:
  512.         (void) Sock_Close(privPtr);
  513.         Fs_EventHandlerDestroy(streamID);
  514.         reply.status == SUCCESS;
  515.         PdevReply(streamID, &reply, "close");
  516.         (void) close(streamID);
  517.         break;
  518.  
  519.  
  520.         /*
  521.          * The client wants data from the server.
  522.          */
  523.         case PDEV_READ:
  524.         if (privPtr->sharePtr->protoIndex == UDP_PROTO_INDEX) {
  525.             /*
  526.              * Special case optimized UDP read request handler.
  527.              * It sends its own reply
  528.              */
  529.             UDP_ReadRequest(privPtr, requestPtr, streamID);
  530.         } else {
  531.             /*
  532.              * Allocate a reply buffer to hold the data from the socket.
  533.              */
  534.             reply.replyBuf = 
  535.                 malloc((unsigned int)requestPtr->hdr.replySize);
  536.             reply.status = Sock_Read( privPtr, 
  537.                 requestPtr->hdr.replySize, reply.replyBuf,
  538.                 &reply.replySize);
  539.             /*
  540.              * Make sure we don't supply more than what was requested.
  541.              */
  542.             if (reply.replySize > replySize) {
  543.             (void) fprintf(stderr, 
  544.               "PdevRequestHandler: gave too much data for READ.\n");
  545.             }
  546.             reply.selectBits = Sock_Select(privPtr, TRUE); 
  547.             PdevReply(streamID, &reply, "read");
  548.             if (reply.replyBuf != (Address) NULL) {
  549.             free(reply.replyBuf);
  550.             }
  551.         }
  552.         break;
  553.  
  554.  
  555.         /*
  556.          * The client wants to send data to the server.
  557.          */
  558.         case PDEV_WRITE_ASYNC:
  559.         case PDEV_WRITE:
  560.         if (ips_Debug) {
  561.             (void) fprintf(stderr, "Pdev_write: %d\n", 
  562.                 requestPtr->hdr.requestSize);
  563.         }
  564.         amount = 0;
  565.         reply.replySize = sizeof(int);
  566.         reply.replyBuf = (Address)&amount;
  567.         if (requestPtr->hdr.requestSize < 0) {
  568.             reply.status = GEN_INVALID_ARG;
  569.         } else {
  570.             reply.status = Sock_Write( privPtr, 
  571.                     requestPtr->param.write.procID,
  572.                     requestPtr->hdr.requestSize,
  573.                     requestData,
  574.                     &amount);
  575.         }
  576.         if (operation == PDEV_WRITE) {
  577.             reply.selectBits = Sock_Select(privPtr, TRUE); 
  578.             PdevReply(streamID, &reply, "write");
  579.         }
  580.         break;
  581.  
  582.         case PDEV_IOCTL: {
  583.             Address outBuffer;
  584.  
  585.             if (requestPtr->hdr.requestSize < 0) {
  586.             reply.status = GEN_INVALID_ARG;
  587.             outBuffer = (Address) NULL;
  588.             } else {
  589.             outBuffer = malloc((unsigned int)requestPtr->hdr.replySize);
  590.  
  591.             reply.status = Sock_IOControl(privPtr,
  592.                     requestPtr->param.ioctl.command,
  593.                         requestPtr->param.ioctl.uid, 
  594.                     requestPtr->hdr.requestSize,
  595.                     requestData,
  596.                     requestPtr->hdr.replySize, outBuffer);
  597.             }
  598.             reply.selectBits = Sock_Select(privPtr, TRUE); 
  599.  
  600.             if (reply.status == SUCCESS) {
  601.             reply.replySize = replySize;
  602.             reply.replyBuf = outBuffer;
  603.             } else {
  604.             reply.replySize = 0;
  605.             reply.replyBuf = (Address) NULL;
  606.             }
  607.             PdevReply(streamID, &reply, "ioctl");
  608.             if (outBuffer != (Address) NULL) {
  609.             free(outBuffer);
  610.             }
  611.         }
  612.         break;
  613.  
  614.         default:
  615.         reply.status = FAILURE;
  616.         PdevReply(streamID, &reply, "??");
  617.         (void) fprintf(stderr, 
  618.             "PdevRequestHandler: unknown operation %d\n",
  619.                 requestPtr->hdr.operation);
  620.         break;
  621.     }
  622.     bufPtrs.requestFirstByte += messageSize;
  623.     }
  624.     if (operation != PDEV_CLOSE) {
  625.     status = Fs_IOControl(streamID, IOC_PDEV_SET_PTRS,
  626.         sizeof(bufPtrs), (Address) &bufPtrs, 
  627.         0, (Address) NULL);
  628.     if (status != SUCCESS){
  629.         Stat_PrintMsg(status, "set ptrs");
  630.         exit(1);
  631.     }
  632.     }
  633. }
  634.  
  635. PdevReply(streamID, replyPtr, caller)
  636.     int            streamID;
  637.     Pdev_Reply    *replyPtr;
  638.     char        *caller;
  639. {
  640.     ReturnStatus    status;
  641.  
  642.     replyPtr->magic = PDEV_REPLY_MAGIC;
  643.     replyPtr->signal = 0;
  644.     replyPtr->code = 0;
  645.     status = Fs_IOControl(streamID, IOC_PDEV_REPLY,
  646.         sizeof(*replyPtr), (Address) replyPtr, 
  647.         0, (Address) NULL);
  648.     if (status != SUCCESS && status != SYS_ARG_NOACCESS){
  649.     Stat_PrintMsg(status, caller);
  650.     exit(1);
  651.     }
  652. }
  653.  
  654.  
  655. /*
  656.  *----------------------------------------------------------------------
  657.  *
  658.  * PrintInfoAndDebug --
  659.  *
  660.  *    Calls the Stat_PrintInfo and Sock_PrintInfo routines and then
  661.  *    turns on debugging. This routine is useful when debugging
  662.  *    is normally off and something goes wrong.
  663.  *
  664.  * Results:
  665.  *    None.
  666.  *
  667.  * Side effects:
  668.  *    Information is printed and debugging turned on.
  669.  *
  670.  *----------------------------------------------------------------------
  671.  */
  672.  
  673. /*ARGSUSED*/
  674. static int
  675. PrintInfoAndDebug(sigNum, sigCode)
  676.     int        sigNum;
  677.     int        sigCode;
  678. {
  679.     Stat_PrintInfo(0,0);
  680.     Sock_PrintInfo(0,0);
  681.     ips_Debug = TRUE;
  682. }
  683.  
  684.  
  685. /*
  686.  *----------------------------------------------------------------------
  687.  *
  688.  * PrintMemStats --
  689.  *
  690.  *    Prints a summary of the memory allocator statistics.
  691.  *    Can be called as a signal handler.
  692.  *
  693.  * Results:
  694.  *    None.
  695.  *
  696.  * Side effects:
  697.  *    Statistics are printed on the standard error stream.
  698.  *
  699.  *----------------------------------------------------------------------
  700.  */
  701.  
  702. /*ARGSUSED*/
  703. static int
  704. PrintMemStats(sigNum, sigCode)
  705.     int        sigNum;        /* Ignored. */
  706.     int        sigCode;    /* Ignored. */
  707. {
  708.     Mem_PrintStats();
  709.     Mem_PrintInUse();
  710. }
  711.  
  712.  
  713. /*
  714.  *----------------------------------------------------------------------
  715.  *
  716.  * ToggleDebug --
  717.  *
  718.  *    Toggles the state of the ips_Debug flag.
  719.  *    Can be called as a signal handler.
  720.  *
  721.  * Results:
  722.  *    None.
  723.  *
  724.  * Side effects:
  725.  *    The debug flag is toggled.
  726.  *
  727.  *----------------------------------------------------------------------
  728.  */
  729.  
  730. /*ARGSUSED*/
  731. static int
  732. ToggleDebug(sigNum, sigCode)
  733.     int        sigNum;        /* Ignored. */
  734.     int        sigCode;    /* Ignored. */
  735. {
  736.     ips_Debug = !ips_Debug;
  737.     (void) fprintf(stderr, "*****  Debugging now  %s  *****\n",
  738.         ips_Debug ? "ON" : "off");
  739. }
  740.  
  741. #ifdef TEST_DISCONNECT
  742.  
  743. /*
  744.  *----------------------------------------------------------------------
  745.  *
  746.  * ToggleDisconnect --
  747.  *
  748.  *    Toggles the state of the ips_Disconnect flag.
  749.  *    Can be called as a signal handler.
  750.  *
  751.  * Results:
  752.  *    None.
  753.  *
  754.  * Side effects:
  755.  *    The  flag is toggled.
  756.  *
  757.  *----------------------------------------------------------------------
  758.  */
  759.  
  760. /*ARGSUSED*/
  761. static int
  762. ToggleDisconnect(sigNum, sigCode)
  763.     int        sigNum;        /* Ignored. */
  764.     int        sigCode;    /* Ignored. */
  765. {
  766.     ips_Disconnect = !ips_Disconnect;
  767.     (void) fprintf(stderr, "*****  Disconnect now  %s  *****\n",
  768.         ips_Disconnect ? "ON" : "off");
  769. }
  770.  
  771. #endif
  772.  
  773.  
  774. /*
  775.  *----------------------------------------------------------------------
  776.  *
  777.  * IPS_GetTimestamp --
  778.  *
  779.  *    Returns the number of milliseconds since midnight.
  780.  *
  781.  * Results:
  782.  *    The # of milliseconds since midnight.
  783.  *
  784.  * Side effects:
  785.  *    None.
  786.  *
  787.  *----------------------------------------------------------------------
  788.  */
  789.  
  790. int
  791. IPS_GetTimestamp()
  792. {
  793.     Time    time;
  794.     Time_Parts    parts;
  795.  
  796.     Sys_GetTimeOfDay(&time, (int *) NULL, (Boolean *) NULL);
  797.  
  798.     Time_ToParts(time.seconds, FALSE, &parts);
  799.     return((((parts.hours * 3600) + (parts.minutes * 60) + 
  800.          parts.seconds) * 1000) + (time.microseconds/ONE_MILLISECOND));
  801. }
  802.  
  803.  
  804. /*
  805.  *----------------------------------------------------------------------
  806.  *
  807.  * IPS_InitPacket --
  808.  *
  809.  *    Initializes a packet by allocating memory for the data and
  810.  *    packet headers and setting up the pointer to the data part
  811.  *    of the packet.
  812.  *
  813.  * Results:
  814.  *    None.
  815.  *
  816.  * Side effects:
  817.  *    Memory is allocated.
  818.  *
  819.  *----------------------------------------------------------------------
  820.  */
  821.  
  822. void
  823. IPS_InitPacket(dataLen, packetPtr)
  824.     int        dataLen;
  825.     register IPS_Packet    *packetPtr;
  826. {
  827.     packetPtr->dataLen = dataLen;
  828.     packetPtr->totalLen = dataLen + IPS_ROOM_FOR_HEADERS;
  829.     packetPtr->base = malloc((unsigned int) packetPtr->totalLen + 4);
  830.     packetPtr->dbase = packetPtr->base + 2;
  831.     packetPtr->data = packetPtr->dbase + IPS_ROOM_FOR_HEADERS;
  832.     if (((unsigned)packetPtr->data & 0x3) != 0) {
  833.     packetPtr->data += 2;
  834.     packetPtr->totalLen += 2;
  835.     }
  836. }
  837.  
  838. f1(iPtr)
  839.     int    *iPtr;
  840. {
  841.     printf("i: %x = %x\n", iPtr, *iPtr);
  842. }
  843.